package top.jacktgq.itheima.netty.protocol_design.groupchat.protocol;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import org.junit.Test;
import top.jacktgq.itheima.netty.protocol_design.groupchat.message.LoginRequestMessage;

/**
 * @Author CandyWall
 * @Date 2021/3/24--12:32
 * @Description
 */
public class TestMessageCodec {
    @Test
    /**
     * 验证消息编解码器的编解码功能是否正确
     */
    public void test1() throws Exception {
        EmbeddedChannel channel = new EmbeddedChannel(new LoggingHandler(LogLevel.DEBUG), new MessageCodec());
        // encode
        LoginRequestMessage loginRequestMessage = new LoginRequestMessage("zhangsan", "123");
        //channel.writeOutbound(loginRequestMessage);

        // decode
        ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer();
        new MessageCodec().encode(null, loginRequestMessage, buffer);

        channel.writeInbound(buffer);
    }

    @Test
    /**
     * 演示半包问题及其解决方案
     */
    public void test2() throws Exception {
        EmbeddedChannel channel = new EmbeddedChannel(
                new LoggingHandler(LogLevel.DEBUG),
                new LengthFieldBasedFrameDecoder(1024, 12, 4, 0, 0),
                new MessageCodec()
        );
        // encode
        LoginRequestMessage loginRequestMessage = new LoginRequestMessage("zhangsan", "123");
        //channel.writeOutbound(loginRequestMessage);

        // decode
        ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer();
        new MessageCodec().encode(null, loginRequestMessage, buffer);

        //channel.writeInbound(buffer);
        // 将完整的消息ByteBuf分成两份进行发送，这时就会发生半包问题
        // 解决方法是添加一个LengthFieldBasedFrameDecoder，没有达到对应的字节数，它会记录着
        // 不会把不完整的消息传递给我们自定义的解码器，直到接收齐了数据才会一次性传递给我们自定义的解码器
        ByteBuf buf1 = buffer.slice(0, 150);
        ByteBuf buf2 = buffer.slice(150, buffer.readableBytes() - 150);
        buf1.retain();
        channel.writeInbound(buf1); // 这里会release一下，引用计数会减1，所以需要在前面先retain一下
        channel.writeInbound(buf2);
    }
}
